#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include <ctype.h>
#define MAXPAL 1000
#define MAXPRI 10000

typedef struct vetorPalavra
{
    char *p;
}vetorPalavra;

vetorPalavra* separaPalavra(char palavra[])
{
    struct vetorPalavra vet[200];
    int i = 0;

    (vet[i]).p = strtok(palavra, ".():;,'?!*-|/%[]><+#");

    while((vet[i]).p != NULL)
    {
          //printf("%s\n",(vet[i]).p);
          i++;
          (vet[i]).p = strtok(NULL, ".():;,'?!*-|/%[]><+#");
    }
    return vet;
}

int palindromo(char *string, int tamanho){
    int i = tamanho-1, j;
    for(j=0; j<(tamanho/2);j++, i--){
        //48 = '0'    57 = '9'     97 = 'a'    122 = 'z'
        if ((tolower(string[j]) < 48 || tolower(string[j]) > 57 && tolower(string[j]) < 97 || tolower(string[j]) > 122) && (j+1<i))//se nao for letra valida, pula
            j++;
        if ((tolower(string[i]) < 48 || tolower(string[i]) > 57 && tolower(string[i]) < 97 || tolower(string[i]) > 122) && (i-1>=j))//se nao for letra valida, pula
            i--;
        if (tolower(string[j])!= tolower(string[i])){
            return 0;//nao e palindromo
        }
    }
        return 1;//e palindromo
}

void anulaMultiplos(int primo[], int m, int sub){
    int i;
    for(i = (sub+1);i <= m; i++){
     if((i%sub) == 0)
       primo[i] = 0;
    }
}

int *crivoErastotenes(int max){
    int i;
    int primo[max];
    for (i = 1; i <= max; i++)
        primo[i] = 1;//inicia o vetor com 1's
    for (i = 2; i <= max; i++)
        if (primo[i] == 1)//evitar processar mais de uma vez
            anulaMultiplos(primo, max, i);//anula multiplos
    return primo;
}

int verificaPrimo(char *string, int tamanho, int *primos){
    int i, soma = 0;
    //faz a soma do ascii
    for(i=0;i < tamanho;i++)
        soma = soma + string[i];
    /*verifica se o numero e primo utilizando o vetor gerado pelo crivo*/
    if(primos[soma]==1)
        return 1;//se for primo retorna 1
    else return 0;//0 c.c
}

int palindromoPalavraPrimo(int *primos, FILE *fp){
    char pa[MAXPAL];
    vetorPalavra *aux;
    int size, retorno, numPalindromos = 0, numPrimos = 0, i;
    clock_t inicioPa = 0 ,fimPa = 0, inicioPr = 0,fimPr = 0;
    double tempoPa = 0, tempoPr = 0;

    inicioPa=clock();
    rewind(fp);//muda o ponteiro para o comeco do arquivo
    while(fscanf(fp,"%s",pa)!=EOF){
        aux = separaPalavra(pa);
        for(i=0; aux[i].p != NULL; i++){
           size = strlen(aux[i].p);//pega o tamanho
           retorno = palindromo(aux[i].p, size);//funcao q retorna 1 se for palindromo e 0 c.c.
           numPalindromos = numPalindromos + retorno;//atualiza numero total de palindromos

           /*se for palindromo, calcula a soma do ascii*/
            if(retorno == 1){
                inicioPr=clock();
                retorno = verificaPrimo(aux[i].p, size, primos);//funcao q retorna 1 se for primo e 0 c.c.
                numPrimos = numPrimos + retorno;
                fimPr=clock();
                tempoPr = tempoPr + ((fimPr-inicioPr)/(CLOCKS_PER_SEC/1000));
            }
        }
    }
    fimPa=clock();
    tempoPa = ((fimPa-inicioPa)/(CLOCKS_PER_SEC/1000)) - tempoPr;
    printf("Total de palindromos %d\n",numPalindromos);
    printf("Tempo utlizado em milisegundos %lf.\n\n",tempoPa);
    printf("Total de numeros primos %d\n",numPrimos);
    printf("Tempo utlizado em milisegundos %lf.\n\n",tempoPr);
    return 0;
}

int palindromoPalavra(FILE *fp){
    char pa[MAXPAL];
    vetorPalavra *aux;
    int size, retorno, numPalindromos = 0, i;
    clock_t inicioPa = 0 ,fimPa = 0;
    double tempoPa = 0;

    inicioPa=clock();
    rewind(fp);//muda o ponteiro para o comeco do arquivo
    while(fscanf(fp,"%s",pa)!=EOF){
        aux = separaPalavra(pa);
        for(i=0; aux[i].p != NULL; i++){
           size = strlen(aux[i].p);//pega o tamanho
           retorno = palindromo(aux[i].p, size);//funcao q retorna 1 se for palindromo e 0 c.c.
           numPalindromos = numPalindromos + retorno;//atualiza numero total de palindromos
        }
    }
    fimPa=clock();
    tempoPa = ((fimPa-inicioPa)/(CLOCKS_PER_SEC/1000));
    printf("Total de palindromos %d\n",numPalindromos);
    printf("Tempo utlizado em milisegundos %lf.\n\n",tempoPa);
    return 0;
}


int palindromoFrase(FILE *fp){
    char frase[1000];
    int tamanho, numFrasePal = 0,retorno;
    clock_t inicioFr = 0 ,fimFr = 0;
    double tempoFr = 0;

    inicioFr=clock();
    rewind(fp);//muda o ponteiro para o comeco do arquivo
    while(fgets(frase,1000,fp)!=NULL){//pega string
        if(strcmp(frase,"\n")==0)
            continue;
        tamanho=strlen(frase);//pega o tamanho
        retorno = palindromo(frase,tamanho);
        numFrasePal = numFrasePal + retorno;
    }
    fimFr=clock();
    tempoFr = ((fimFr-inicioFr)/(CLOCKS_PER_SEC/1000));
    printf("Total de frases palindromos %d\n",numFrasePal);
    printf("Tempo utlizado em milisegundos %lf.\n\n",tempoFr);

    return 0;
}



int main(int argc, char *argv[]){
    int retorno,*primos;
    unsigned int numPrimos = 0;
    int soma = 0,i,j=0;
    FILE *fp, *fp2;

    printf("\n\nCalculando...\n\n");

    primos = (int*)malloc(MAXPRI*sizeof(int));//aloca vetor para o crivo
    primos = crivoErastotenes(MAXPRI);

    if(!(fp = fopen("wikipedia.txt","r"))){//abre o arquivo
        printf("Erro! Verifique se o arquivo existe!\n");
  		exit(1);
    }

    printf("Arquivo wikipedia.txt:\n\n");
    palindromoPalavraPrimo(primos, fp);
    fclose(fp);

    if(!(fp2 = fopen("shakespe.txt","r"))){//abre o arquivo
        printf("Erro! Verifique se o arquivo existe!\n");
  		exit(1);
    }

    printf("\n\nArquivo shakespe.txt:\n\n");
    palindromoFrase(fp2);
    palindromoPalavra(fp2);


    free(primos);
    fclose(fp2);
    return 0;
}
